const {Vri, errorTemplates, ErrorMessage} = require('vri')
const toolCode = require('../tool/code')

Object.assign(errorTemplates, {
  type: '[key]类型必须为[schema]',
  must: '缺少必选属性[key]',
  max: '[key]不能大于[schema]',
  min: '[key]不能小于[schema]',
  ContainsLetters: '[key]必须包含字母',
  includeNumber: '[key]必须包含数字',
  regEx: '[key]正则表达式不匹配',
})

/**长度不能超过255 */
const len255 = {
  type: 'string',
  max: 255,
  min: 1,
}

const id = {
  type: 'number',
  must: true,
}

const limit = {
  page: {
    type: 'number',
    min: 1,
  },
  size: {
    type: 'number',
    min: 1,
  },
}

const img = {
  type: 'string',
  regEx: /^[A-Za-z0-9\.]+$/i,
  max: 40,
}

const userInfo = {
  username: {
    min: 2,
    max: 16,
    regEx: /^[\u4E00-\u9FA5A-Za-z0-9_\-]+$/i,
    must: true,
  },
  password: {
    min: 6,
    max: 16,
    must: true,
    ContainsLetters: true,
    includeNumber: true,
  },
  mail: {
    type: 'string',
    regEx: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/i,
    must: true,
  },
}

const commodityInfo = {
  classifyid: id,
  brandid: id,
  name: {
    type: 'string',
    max: 255,
    min: 2,
    must: true,
  },
  price: {
    type: 'number',
    min: 0.01,
    must: true,
  },
  stock: {
    type: 'number',
    min: 0,
    must: true,
  },
  tags: {
    type: 'array',
    must: true,
    item: {
      type: 'string',
    },
    pretreat(value) {
      return Array.from(new Set(value)).join(',')
    },
  },
  image: {
    type: 'array',
    must: true,
    item: img,
    max: 9,
    pretreat(value) {
      return Array.from(new Set(value)).join(',')
    },
  },
  specification: {
    type: 'array',
    must: true,
    item: {
      type: 'string',
    },
    pretreat(value) {
      return Array.from(new Set(value)).join(',')
    },
  },
}

const classifyInfo = {
  name: {
    type: 'string',
    must: true,
  },
  parent: {
    type: 'number',
    must: true,
  },
  grade: {
    type: 'number',
    max: 2,
    min: 0,
    must: true,
  },
}

const del = new Vri({
  type: 'object',
  attr: {
    id,
  },
})

const dels = new Vri({
  type: 'object',
  attr: {
    ids: {
      type: 'array',
      item: {
        type: 'number',
      },
      must: true,
    },
  },
})

const qw = {
  ...len255,
  pretreat(v) {
    return `%${v}%`
  },
}

module.exports = {
  user: {
    login: new Vri({
      type: 'object',
      attr: {
        username: {
          min: 2,
          max: 16,
          must: true,
        },
        password: {
          min: 6,
          max: 16,
          must: true,
          ContainsLetters: true,
          includeNumber: true,
        },
      },
    }),
    enroll: new Vri({
      type: 'object',
      attr: {
        ...userInfo,
        authCode: {
          type: 'string',
          must: true,
          custom(context) {
            const {value, param} = context
            if (toolCode.has(param.mail, value)) {
              return {
                adopt: true,
                value,
              }
            } else {
              const error = new ErrorMessage(context)
              error.template = '验证码不正确或已过期'
              return {
                adopt: false,
                value,
                error,
              }
            }
          },
        },
      },
    }),
    verifycode: new Vri({
      type: 'object',
      attr: {
        mail: userInfo.mail,
        authCode: {
          type: 'string',
          must: true,
          custom(context) {
            const {value, param} = context
            if (toolCode.has(param.mail, value)) {
              return {
                adopt: true,
                value,
              }
            } else {
              const error = new ErrorMessage(context)
              error.template = '验证码不正确或已过期'
              return {
                adopt: false,
                value,
                error,
              }
            }
          },
        },
      },
    }),
    authCode: new Vri({
      type: 'object',
      attr: {
        mail: {
          type: 'string',
          regEx: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/i,
          must: true,
        },
      },
    }),
    portrait: new Vri({
      type: 'object',
      attr: {
        portrait: {
          type: 'string',
          regEx: /^[a-z0-9]{2,32}\.[a-z]{1,5}$/,
        },
      },
    }),
    username: new Vri({
      type: 'object',
      attr: {
        username: userInfo.username,
      },
    }),
    modifyname: new Vri({
      type: 'object',
      attr: {
        username: userInfo.username,
      },
    }),
    message: new Vri({
      type: 'object',
      attr: {
        ...limit,
      },
    }),
    read: new Vri({
      type: 'object',
      attr: {
        ids: {
          type: 'array',
          item: {
            type: 'number',
          },
        },
      },
    }),
    power: new Vri({
      type: 'object',
      attr: {
        id,
        power: {
          type: 'array',
          item: {
            type: 'string',
            min: 1,
          },
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
      },
    }),
    search: new Vri({
      type: 'object',
      attr: {
        qw,
        ...limit,
      },
    }),
    fromid: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
  },
  commodity: {
    fromid: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    add: new Vri({
      type: 'object',
      attr: {
        ...commodityInfo,
      },
    }),
    search: new Vri({
      type: 'object',
      attr: {
        qw,
        classifyid: {
          type: 'number',
        },
        brandid: {
          type: 'number',
        },
        recycle: {
          type: 'boolean',
        },
        all: {
          type: 'boolean',
        },
        ...limit,
      },
    }),
    modify: new Vri({
      type: 'object',
      attr: {
        id: {
          type: 'number',
          must: true,
        },
        classifyid: {
          type: 'number',
        },
        brandid: {
          type: 'number',
        },
        name: {
          type: 'string',
          max: 255,
          min: 2,
        },
        price: {
          type: 'number',
          min: 0.01,
        },
        stock: {
          type: 'number',
          min: 0,
        },
        tags: {
          type: 'array',
          item: {
            type: 'string',
          },
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
        image: {
          type: 'array',
          item: {
            type: 'string',
            regEx: /^[A-Z0-9\.]+$/i,
          },
          max: 9,
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
        publish: {
          type: 'number',
          min: 0,
          max: 1,
        },
        specification: {
          type: 'array',
          item: {
            type: 'string',
          },
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
      },
    }),
    comment: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    publish: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    del,
    dels,
  },
  classify: {
    fromid: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    record: new Vri({
      type: 'object',
      attr: {
        ...limit,
      },
    }),
    add: new Vri({
      type: 'object',
      attr: {
        ...classifyInfo,
      },
    }),
    move: new Vri({
      type: 'object',
      attr: {
        id,
        grade: classifyInfo.grade,
        parent: classifyInfo.parent,
      },
    }),
    rename: new Vri({
      type: 'object',
      attr: {
        id,
        name: classifyInfo.name,
      },
    }),
    list: new Vri({
      type: 'object',
      attr: {
        grade: {
          type: 'number',
          max: 2,
          min: 0,
        },
        parent: {
          type: 'number',
        },
        id: {
          type: 'number',
        },
      },
    }),
    parent: new Vri({
      type: 'object',
      attr: {
        id: {
          type: 'number',
          must: true,
        },
      },
    }),
    del,
    dels,
  },
  shoppingCart: {
    add: new Vri({
      type: 'object',
      attr: {
        commodityid: {
          type: 'number',
          must: true,
        },
        specification: {
          must: true,
          ...len255,
        },
        number: {
          type: 'number',
          min: 1,
          must: true,
        },
      },
    }),
    select: new Vri({
      type: 'object',
      attr: {
        id,
        selected: {
          type: 'boolean',
          must: true,
        },
      },
    }),
    selectAll: new Vri({
      type: 'object',
      attr: {
        selected: {
          type: 'boolean',
          must: true,
        },
      },
    }),
    number: new Vri({
      type: 'object',
      attr: {
        id,
        number: {
          type: 'number',
          must: true,
          min: 1,
        },
      },
    }),
    fromid: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    order: new Vri({
      type: 'object',
      attr: {
        ids: {
          type: 'array',
          item: {
            type: 'number',
          },
          must: true,
        },
      },
    }),
    del,
    dels,
  },
  brand: {
    fromid: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    search: new Vri({
      type: 'object',
      attr: {
        qw,
        ...limit,
      },
    }),
    add: new Vri({
      type: 'object',
      attr: {
        name: {
          must: true,
          ...len255,
        },
        classifys: {
          type: 'array',
          item: {
            type: 'number',
          },
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
        logo: {
          must: true,
          ...img,
        },
      },
    }),
    modify: new Vri({
      type: 'object',
      attr: {
        id,
        name: {
          must: true,
          ...len255,
        },
        classifys: {
          type: 'array',
          item: {
            type: 'number',
          },
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
        logo: {
          must: true,
          ...len255,
        },
      },
    }),
    del,
    dels,
  },
  comment: {
    details: new Vri({
      type: 'object',
      attr: {
        id,
      },
    }),
    add: new Vri({
      type: 'object',
      attr: {
        id: id,
        main: {
          must: true,
          ...len255,
        },
        image: {
          type: 'array',
          item: {
            type: 'string',
            regEx: /^[A-Za-z0-9\.]+$/i,
          },
          max: 6,
          pretreat(value) {
            return Array.from(new Set(value)).join(',')
          },
        },
        evaluate: {
          type: 'number',
          must: true,
          min: 1,
          max: 10,
        },
      },
    }),
    reply: new Vri({
      type: 'object',
      attr: {
        reply: id,
        main: {
          ...len255,
        },
      },
    }),
    agree: new Vri({
      type: 'object',
      attr: {
        id,
        agree: {
          type: 'boolean',
          must: true,
        },
      },
    }),
    del,
  },
  shop: {
    add: new Vri({
      type: 'object',
      attr: {
        name: {
          ...len255,
        },
        describe: {
          must: true,
          ...len255,
        },
        cover: {
          must: true,
          ...img,
        },
      },
    }),
    modify: new Vri({
      type: 'object',
      attr: {
        name: {
          ...len255,
        },
        describe: {
          must: true,
          ...len255,
        },
        cover: {
          ...img,
        },
      },
    }),
  },
  order: {
    fromid: new Vri({
      type: 'object',
      attr: {
        id: {
          type: 'number',
          must: true,
        },
      },
    }),
  },
}
